package com.xrh.WordStudy.utils;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.poi.util.Units;
import org.apache.poi.wp.usermodel.HeaderFooterType;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFFooter;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTShd;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcBorders;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder;

import com.xrh.WordStudy.common.BusinessException;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FastByteArrayOutputStream;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Test {

	/**
	    A4纸页面宽度
        // 获取页面的宽度（这里使用A4纸的宽度作为示例，单位转换为EMU，即English Metric Unit）
        // 注意：POI没有直接提供获取页面宽度的API，这里假设页面宽度为A4纸的宽度（595点，1点=127/4800英寸）
        // 并且将其转换为EMU（1英寸=914400 EMU）
        long pageSizeWidthInEMU = (long) (595 * 914400 / 72 * 4800 / 127);
 
        // 设置表格的宽度为页面宽度减去一些边距（这里假设边距为72点，同样转换为EMU）
        long tableWidthInEMU = pageSizeWidthInEMU - (2 * 72 * 914400 / 72);
	 */
	private static final long A4_WIDTH = 13222078;
	
	//A4纸页眉和页脚宽度,是body宽度的80%
	private static final long A4_HEADER_FOOT_WIDTH = 10577662;
	
	public static void main(String[] args) throws Exception {
		
	     // 创建一个新的空白Word文档
        XWPFDocument document = new XWPFDocument();

        // 创建一个段落 , 并设置对齐方式
        addParagraph(document , "B你好, 勇士!");
        
        File file = new File("D:/图片/数垚logo.png");
        
        //页眉添加一张图片
        addLeftPictureRightContentForPageHeader(document, new FileInputStream(file), file.getName(), "数垚科技有限公司");
        
        //给页脚添加一句话
        addContentForPageFoot(document, "联系我们 : 浙江省杭州市滨江区东信科技园启迪楼");
        
        //模拟表格数据
        TableHeaderData tableHeaderData = createTableDemoData();
        
        //创建一个模拟表格数据
        createTable(document, tableHeaderData.getHeaderWidthPercentMap(), tableHeaderData.getRowDataList());
        
        //把文件写到输出流中
        write(document, new FileOutputStream(new File("D:/HelloWorld.docx")));
	}
	
	/**
	 * @function  给页脚添加内容
	 * @param  XWPFDocument document 
	 * @author 肖荣辉
	 * @date 2024年12月6日
	*/
	public static void addContentForPageFoot(XWPFDocument document ,  String content ) {
		
		// 获取文档的页眉部分，如果不存在则创建一个
		XWPFFooter foot = document.createFooter(HeaderFooterType.FIRST);
		
		XWPFParagraph paragraph = foot.createParagraph();
		
		XWPFRun run = paragraph.createRun();
		
		run.setText(content);
	}
	
	/**
	 * @function  给页眉添加左右侧都是内容
	 * @param  XWPFDocument document 
	 * @author 肖荣辉
	 * @date 2024年12月6日
	*/
	public static void addLeftRightContentForPageHeader(XWPFDocument document , String leftContent , String rightContent ) {
		
		// 获取文档的页眉部分，如果不存在则创建一个
		XWPFHeader header = document.createHeader(HeaderFooterType.FIRST);
		
	    // 创建一个表格 , 先只创建一行表格头行
        XWPFTable table = header.createTable(1 , 2);	 // 初始时只创建一行，后续可以添加更多行
        
        //左侧的单元格
        XWPFTableCell leftCell = table.getRow(0).getCell(0); 
        
        //无边框
        unsetTableCellBorder(leftCell);

        leftCell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.BOTTOM);
        
        XWPFParagraph leftParagraph = leftCell.getParagraphs().get(0);
        
        leftParagraph = leftParagraph == null ?  leftCell.addParagraph() : leftParagraph; 
        
        leftParagraph.setAlignment(ParagraphAlignment.LEFT);
        
        //页眉和页脚的宽度和body的宽度是不一样
        leftCell.getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(A4_HEADER_FOOT_WIDTH/2));
        
        XWPFRun leftParagraphRun =  leftParagraph.createRun();
        
        leftParagraphRun.setText(leftContent);
        
        //右侧单元格
        XWPFTableCell rightCell = table.getRow(0).getCell(1); 
        
        //无边框
        unsetTableCellBorder(rightCell);
        
        rightCell.getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(A4_HEADER_FOOT_WIDTH/2));
        
        rightCell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.BOTTOM);
        
        XWPFParagraph rightParagraph = rightCell.getParagraphs().get(0);
        
        rightParagraph = rightParagraph == null ?  rightCell.addParagraph() : rightParagraph; 
        
        rightParagraph.setAlignment(ParagraphAlignment.RIGHT);
        
        XWPFRun rightParagraphRun =  rightParagraph.createRun();
        
        rightParagraphRun.setText(rightContent);
	    
	}
	
	/**
	 * @function  给页眉添加图片和内容(左侧是图片, 右侧是文字)
	 * @param  XWPFDocument document 
	 * @author 肖荣辉
	 * @date 2024年12月6日
	*/
	public static void addLeftPictureRightContentForPageHeader(XWPFDocument document , InputStream inputStream , String fileName , String content ) {
		
		// 获取文档的页眉部分，如果不存在则创建一个
		XWPFHeader header = document.createHeader(HeaderFooterType.FIRST);
		
	    // 创建一个表格 , 先只创建一行表格头行
        XWPFTable table = header.createTable(1 , 2);	 // 初始时只创建一行，后续可以添加更多行
        
        //左侧的单元格
        XWPFTableCell leftCell = table.getRow(0).getCell(0); 
        
        //无边框
        unsetTableCellBorder(leftCell);

        leftCell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.BOTTOM);
        
        XWPFParagraph leftParagraph = leftCell.getParagraphs().get(0);
        
        leftParagraph = leftParagraph == null ?  leftCell.addParagraph() : leftParagraph; 
        
        leftParagraph.setAlignment(ParagraphAlignment.LEFT);
        
        //页眉和页脚的宽度和body的宽度是不一样
        leftCell.getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(A4_HEADER_FOOT_WIDTH/2));
        
        addPicture(leftParagraph , inputStream , fileName);
        
        //右侧单元格
        XWPFTableCell rightCell = table.getRow(0).getCell(1); 
        
        //无边框
        unsetTableCellBorder(rightCell);
        
        rightCell.getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(A4_HEADER_FOOT_WIDTH/2));
        
        rightCell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.BOTTOM);
        
        XWPFParagraph rightParagraph = rightCell.getParagraphs().get(0);
        
        rightParagraph = rightParagraph == null ?  rightCell.addParagraph() : rightParagraph; 
        
        rightParagraph.setAlignment(ParagraphAlignment.RIGHT);
        
        XWPFRun rightParagraphRun =  rightParagraph.createRun();
        
        rightParagraphRun.setText(content);
	    
	}
	
	/**
	 * @function 表格单元格设置为无边框
	 * @param cell
	 * @author 肖荣辉
	 * @date 2024年12月6日
	*/
	public static void unsetTableCellBorder(XWPFTableCell cell) {
		
		// 获取单元格的CTTc（表格单元格）对象
        CTTc ctTc = cell.getCTTc();
        
        // 如果CTTcPr（表格单元格属性）不存在，则创建一个新的
        if (!ctTc.isSetTcPr()) 
            ctTc.addNewTcPr();
        
        // 获取或创建CTTcPr中的CTBorders（边框）对象
        CTTcPr tcPr = ctTc.getTcPr();
        
        if (!tcPr.isSetTcBorders()) 
            tcPr.addNewTcBorders();
        
        // 设置无边线(如果还有虚线 , 是wps上面的视图, 表格虚框设置导致的. 去掉就行)
        CTTcBorders borders = tcPr.getTcBorders();
        
        borders.addNewTop().setVal(STBorder.NIL);
        borders.addNewBottom().setVal(STBorder.NIL);
        borders.addNewRight().setVal(STBorder.NIL);
        borders.addNewLeft().setVal(STBorder.NIL);
		
	}
	
	/**
	 * @function 创建一个表格
	 * @param headerWidthPercentMap 表格头 - 宽度百分比对照map (value : 直接填整型的百分比)
	 * @param rowDataList
	 * @author 肖荣辉
	 * @date 2024年12月5日
	*/
	public static void createTable(XWPFHeader document , LinkedHashMap<String , Integer> headerWidthPercentMap , List<List<String>> rowDataList) {
		
		//表格头 - 宽度百分比对照map 为空则返回
		if(MapUtil.isEmpty(headerWidthPercentMap))
			return;
		
		int sum = headerWidthPercentMap.values().stream().reduce(0, Integer::sum);
		
		if(sum != 100) {
			log.info("表格每一列加起来的百分比为: {} , 没有100 , 忽略.." , sum);
		}
		
        List<String> headers = new ArrayList<String>(headerWidthPercentMap.keySet());
        
		//列数 , 取决于表格头
		int cols = headers.size();
		
		// 创建一个表格 , 先只创建一行表格头行
        XWPFTable table = document.createTable(1 , cols);	 // 初始时只创建一行，后续可以添加更多行
        
        //每一列索引和长度对照map
        Map<Integer , Long> indexWidthMap = new HashMap<Integer , Long>();
        
        // 遍历表格的列，并设置每列的宽度
        for (int i = 0; i < cols; i++) {
        	
        	String headerName  = headers.get(i);
        	
            XWPFTableCell cell = table.getRow(0).getCell(i); // 获取第一行的第i列单元格
            
            long cellWidth = (long) Math.floor(A4_HEADER_FOOT_WIDTH * headerWidthPercentMap.get(headerName) / 100);
            
            indexWidthMap.put(i, cellWidth);
            
            // 设置单元格的宽度（注意：这里设置的是单元格的网格宽度，不是实际显示的宽度）
            // 单元格的实际显示宽度还受到单元格内容、边框、边距等因素的影响
            cell.getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(cellWidth));
            
            // 获取单元格中的第一个段落
            XWPFParagraph paragraph = cell.getParagraphs().get(0);
            
            // 如果段落不存在，则创建一个新的段落
            paragraph = paragraph == null ?  cell.addParagraph() : paragraph; 
            
            //撑高表格头
            paragraph.setSpacingBefore(50);
            paragraph.setSpacingAfter(50);
            
            XWPFRun run =  paragraph.createRun();
            
            //设置为粗体
            run.setBold(true);
            
            run.setText(headerName);
            
            // 设置段落水平居中
            paragraph.setAlignment(ParagraphAlignment.CENTER); 
            
            //垂直居中
            cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
            
            //设置背景色
            setCellBackgroundColor(cell, "D3D3D3");
        }
        
        if(CollUtil.isEmpty(rowDataList))
        	return;
        
        //添加数据
        for(List<String> rowData : rowDataList) {
        	
            //创建数据行
            XWPFTableRow  row = table.createRow();
            
        	 for (int i = 0; i < cols; i++) {
        		 
        		 String value = i < rowData.size() ? rowData.get(i) : "";
        		 
        	     value = StrUtil.blankToDefault(value, "");
        	        
                 XWPFTableCell cell = row.getCell(i); 
                 
                 //宽度和表头保持一致
                 cell.getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(indexWidthMap.get(i)));
                 
                 cell.setText(value);
                 
                 // 获取单元格中的第一个段落
                 XWPFParagraph paragraph = cell.getParagraphs().get(0);
                 
                 paragraph.setSpacingBefore(10);
                 paragraph.setSpacingAfter(10);
                 
                 // 如果段落不存在，则创建一个新的段落
                 paragraph = paragraph == null ?  cell.addParagraph() : paragraph; 
                 
                 // 设置段落水平居中
                 paragraph.setAlignment(ParagraphAlignment.CENTER); 
                 
                 //垂直居中
                 cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
        		 
        	 }
        	 
        }
        
	}
	
	/**
	 * @function  给页眉添加图片
	 * @param  XWPFDocument document 
	 * @author 肖荣辉
	 * @date 2024年12月6日
	*/
	public static void addPictureForPageHeader(XWPFDocument document , InputStream inputStream , String fileName ) {
		
		// 获取文档的页眉部分，如果不存在则创建一个
		XWPFHeader header = document.createHeader(HeaderFooterType.FIRST);
		
	    XWPFParagraph headerParagraph = header.getParagraphArray(0);
	    
	    headerParagraph = headerParagraph == null ? header.createParagraph() : headerParagraph;
	    
	    addPicture(headerParagraph, inputStream, fileName);
	    
	}

	
	/**
	 * @function  给页眉添加内容
	 * @param  XWPFDocument document 
	 * @author 肖荣辉
	 * @date 2024年12月6日
	*/
	public static void addContentForPageHeader(XWPFDocument document ,   String content ,  boolean isBold , Double fontSize) {
		
		// 获取文档的页眉部分，如果不存在则创建一个
		XWPFHeader header = document.createHeader(HeaderFooterType.FIRST);
		
	    XWPFParagraph headerParagraph = header.getParagraphArray(0);
	    
	    headerParagraph = headerParagraph == null ? header.createParagraph() : headerParagraph;
	    
	    XWPFRun headerRun = headerParagraph.createRun();
	    
	    headerRun.setText("	" + content);
	    
	    headerRun.setFontSize(12);
	    
	    headerRun.setBold(isBold);
	    
	    if(fontSize != null)
	    	headerRun.setFontSize(fontSize);
	    
	}
	
	/**
	 * @function 给段落添加图片(尺寸为指定尺寸)
	 * @param paragraph 段落对象
	 * @param inputStream 输入流
	 * @param fileName 文件名称
	 * @param width 宽度
	 * @param height 高度
	 * @author 肖荣辉
	 * @date 2024年12月5日
	*/
	public static void addPicture(XWPFDocument document , InputStream inputStream , String fileName  , int width , int height) {
		addPicture(document.createParagraph(), inputStream, fileName, width, height);
	}
	
	
	/**
	 * @function 给段落添加图片(尺寸为指定尺寸)
	 * @param paragraph 段落对象
	 * @param inputStream 输入流
	 * @param fileName 文件名称
	 * @param width 宽度
	 * @param height 高度
	 * @author 肖荣辉
	 * @date 2024年12月5日
	 */
	public static void addPicture(XWPFParagraph paragraph , InputStream inputStream , String fileName  , int width , int height) {
		
		try {
			
			//在段落中创建图片
			XWPFRun run = paragraph.createRun();
			
			run.addPicture(inputStream , Document.PICTURE_TYPE_PNG , fileName , Units.toEMU(width) , Units.toEMU(height));
			
			inputStream.close();
			
		} catch (Exception e) {
			throw new BusinessException("word文档写入图片"+fileName+"错误==>" +  e.getMessage());
		}
		
	}
	
	/**
	 * @function 给段落添加图片(尺寸为图片的原始尺寸)
	 * @param paragraph 段落对象
	 * @param inputStream 输入流
	 * @param fileName 文件名称
	 * @author 肖荣辉
	 * @date 2024年12月5日
	*/
	public static void addPicture(XWPFDocument document , InputStream inputStream , String fileName) {
		addPicture(document.createParagraph(), inputStream, fileName);
	}
	
	/**
	 * @function 给段落添加图片 (尺寸为图片的原始尺寸)
	 * @param paragraph 段落对象
	 * @param inputStream 输入流
	 * @param fileName 文件名称
	 * @author 肖荣辉
	 * @date 2024年12月5日
	 */
	public static void addPicture(XWPFParagraph paragraph , InputStream inputStream , String fileName) {
		
		try {
			
			FastByteArrayOutputStream bos = IoUtil.read(inputStream);
			
			byte[] buf = bos.toByteArray();
			
			ByteArrayInputStream bis = new ByteArrayInputStream(buf);
			
			BufferedImage image = ImageIO.read(bis);
				 
            // 获取图片的原始尺寸
            int width = image.getWidth();
            
            int height = image.getHeight();
                
			//在段落中创建图片
			XWPFRun run = paragraph.createRun();
			
			run.addPicture(new ByteArrayInputStream(buf) , Document.PICTURE_TYPE_PNG , fileName , Units.toEMU(width) , Units.toEMU(height));
			
			inputStream.close();
			
		} catch (Exception e) {
			throw new BusinessException("word文档写入图片"+fileName+"错误==>" +  e.getMessage());
		}
		
	}
	
	/**
	 * @function 把文件写到输出流中
	 * @param document
	 * @param outputStream
	 * @author 肖荣辉
	 * @date 2024年12月5日
	*/
	public static void write(XWPFDocument document , OutputStream outputStream) {
		
	   try {
		   
		   document.write(outputStream);
		    
		   outputStream.flush();
		    
		   outputStream.close();
		   
		   document.close();
		   
		} catch (Exception e) {
			throw new BusinessException("word文档写到输出流中错误==>" +  e.getMessage());
		} 
	      
	}
	
	/**
	 * @function 创建一个模拟表格数据
	 * @author 肖荣辉
	 * @date 2024年12月5日
	*/
	public static TableHeaderData createTableDemoData() {
		
        LinkedHashMap<String, Integer> headerWidthPercentMap = new LinkedHashMap<String, Integer>();
        
        headerWidthPercentMap.put("序号", 5);
        headerWidthPercentMap.put("姓名", 25);
        headerWidthPercentMap.put("年龄", 20);
        headerWidthPercentMap.put("爱好", 20);
        headerWidthPercentMap.put("性别", 10);
        headerWidthPercentMap.put("星座", 20);
        
        List<List<String>> rowDataList = new ArrayList<List<String>>();

        for(int i = 0 ; i < 10 ; i ++) {
        	
        	List<String> rowData  = CollUtil.newArrayList((i + 1) + "" , "小明" + i , i + 10 + "" , "篮球" , "男" , "白羊座");
        	
        	rowDataList.add(rowData);
        }
		
		return new TableHeaderData(headerWidthPercentMap, rowDataList);
	}
	
	/**
	 * @function 表格头和数据类
	 * @author 肖荣辉
	 * @date 2024年12月5日
	*/
	@Data
	@AllArgsConstructor
	@NoArgsConstructor
	public static class TableHeaderData{
		
		 //表格头 - 宽度百分比对照map  (百分比加起来要等于100)
		 private LinkedHashMap<String, Integer> headerWidthPercentMap;
		 
		 //表格内容数据
		 private List<List<String>> rowDataList;
	}
	
	
	/**
	 * @function 创建一个平均分配宽度的表格
	 * @param headers 表格头 - 宽度百分比对照map (value : 直接填整型的百分比)
	 * @param rowDataList
	 * @author 肖荣辉
	 * @date 2024年12月5日
	*/
	public static void createTable(XWPFDocument document , List<String> headers , List<List<String>> rowDataList ) {
		
		if(CollUtil.isEmpty(headers))
			return;
		
		int percent = (int) Math.floor(100/headers.size());
		
		LinkedHashMap<String, Integer> headerWidthPercentMap = new LinkedHashMap<String, Integer>();
		
		for(String header : headers) {
			headerWidthPercentMap.put(header, percent);
		}
		
		createTable(document, headerWidthPercentMap, rowDataList); 
	}
	
	/**
	 * @function 添加段落
	 * @param document 文档
	 * @param paragraphAlignment 对齐方式
	 * @param content 内容
	 * @param isBold 是否加粗
	 * @author 肖荣辉
	 * @date 2024年12月5日
	*/
	public static void addParagraph(XWPFDocument document  ,  String content) {
		addParagraph(document , ParagraphAlignment.LEFT , content , false, null);
	}
	
	/**
	 * @function 添加段落
	 * @param document 文档
	 * @param content 内容
	 * @param isBold 是否加粗
	 * @author 肖荣辉
	 * @date 2024年12月5日
	*/
	public static void addParagraph(XWPFDocument document  , String content , boolean isBold) {
		addParagraph(document , ParagraphAlignment.LEFT , content , false, null);
	}
	
	/**
	 * @function 添加段落
	 * @param document 文档
	 * @param paragraphAlignment 对齐方式
	 * @param content 内容
	 * @param isBold 是否加粗
	 * @author 肖荣辉
	 * @date 2024年12月5日
	*/
	public static void addParagraph(XWPFDocument document , ParagraphAlignment paragraphAlignment  ,  String content) {
		addParagraph(document, paragraphAlignment, content, false, null);
	}
	
	/**
	 * @function 添加段落
	 * @param document 文档
	 * @param paragraphAlignment 对齐方式
	 * @param content 内容
	 * @param isBold 是否加粗
	 * @author 肖荣辉
	 * @date 2024年12月5日
	*/
	public static void addParagraph(XWPFDocument document , ParagraphAlignment paragraphAlignment  ,  String content ,  boolean isBold) {
		addParagraph(document, paragraphAlignment, content, isBold, null);
	}
		
		
	/**
	 * @function 添加段落
	 * @param document 文档
	 * @param paragraphAlignment 对齐方式
	 * @param content 内容
	 * @param isBold 是否加粗
	 * @param fontSize 字体大小
	 * @author 肖荣辉
	 * @date 2024年12月5日
	*/
	public static void addParagraph(XWPFDocument document , ParagraphAlignment paragraphAlignment  ,  String content ,  boolean isBold , Double fontSize) {
		
	      // 创建一个段落 , 并设置对齐方式
        XWPFParagraph paragraph = document.createParagraph();
        
        paragraph.setAlignment(paragraphAlignment);
        
        XWPFRun run =paragraph.createRun();
        
        run.setText(content);
        
        if(fontSize != null)
        	run.setFontSize(fontSize);
		
        run.setBold(isBold);
        
	}
	
	/**
	 * @function 创建一个表格
	 * @param headerWidthPercentMap 表格头 - 宽度百分比对照map (value : 直接填整型的百分比)
	 * @param rowDataList
	 * @author 肖荣辉
	 * @date 2024年12月5日
	*/
	public static void createTable(XWPFDocument document , LinkedHashMap<String, Integer> headerWidthPercentMap , List<List<String>> rowDataList ) {
		
		//表格头 - 宽度百分比对照map 为空则返回
		if(MapUtil.isEmpty(headerWidthPercentMap))
			return;
		
		int sum = headerWidthPercentMap.values().stream().reduce(0, Integer::sum);
		
		if(sum != 100) {
			log.info("表格每一列加起来的百分比为: {} , 没有100 , 忽略.." , sum);
		}
		
        List<String> headers = new ArrayList<String>(headerWidthPercentMap.keySet());
        
		//列数 , 取决于表格头
		int cols = headers.size();
		
		// 创建一个表格 , 先只创建一行表格头行
        XWPFTable table = document.createTable(1 , cols);	 // 初始时只创建一行，后续可以添加更多行
        
        //剩余
        long sy = A4_WIDTH;
        
        //每一列索引和长度对照map
        Map<Integer , Long> indexWidthMap = new HashMap<Integer , Long>();
        
        // 遍历表格的列，并设置每列的宽度
        for (int i = 0; i < cols; i++) {
        	
        	String headerName  = headers.get(i);
        	
            XWPFTableCell cell = table.getRow(0).getCell(i); // 获取第一行的第i列单元格
            
            long cellWidth = (long) Math.floor(sy * headerWidthPercentMap.get(headerName) / 100);
            
            indexWidthMap.put(i, cellWidth);
            
            // 设置单元格的宽度（注意：这里设置的是单元格的网格宽度，不是实际显示的宽度）
            // 单元格的实际显示宽度还受到单元格内容、边框、边距等因素的影响
            cell.getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(cellWidth));
            
            // 获取单元格中的第一个段落
            XWPFParagraph paragraph = cell.getParagraphs().get(0);
            
            // 如果段落不存在，则创建一个新的段落
            paragraph = paragraph == null ?  cell.addParagraph() : paragraph; 
            
            //撑高表格头
            paragraph.setSpacingBefore(50);
            paragraph.setSpacingAfter(50);
            
            XWPFRun run =  paragraph.createRun();
            
            //设置为粗体
            run.setBold(true);
            
            run.setText(headerName);
            
            // 设置段落水平居中
            paragraph.setAlignment(ParagraphAlignment.CENTER); 
            
            //垂直居中
            cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
            
            //设置背景色
            setCellBackgroundColor(cell, "D3D3D3");
        }
        
        if(CollUtil.isEmpty(rowDataList))
        	return;
        
        //添加数据
        for(List<String> rowData : rowDataList) {
        	
            //创建数据行
            XWPFTableRow  row = table.createRow();
            
        	 for (int i = 0; i < cols; i++) {
        		 
        		 String value = i < rowData.size() ? rowData.get(i) : "";
        		 
        	     value = StrUtil.blankToDefault(value, "");
        	        
                 XWPFTableCell cell = row.getCell(i); 
                 
                 //宽度和表头保持一致
                 cell.getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(indexWidthMap.get(i)));
                 
                 cell.setText(value);
                 
                 // 获取单元格中的第一个段落
                 XWPFParagraph paragraph = cell.getParagraphs().get(0);
                 
                 paragraph.setSpacingBefore(10);
                 paragraph.setSpacingAfter(10);
                 
                 // 如果段落不存在，则创建一个新的段落
                 paragraph = paragraph == null ?  cell.addParagraph() : paragraph; 
                 
                 // 设置段落水平居中
                 paragraph.setAlignment(ParagraphAlignment.CENTER); 
                 
                 //垂直居中
                 cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
        		 
        	 }
        	 
        }
        
	}
	
	// 设置单元格背景色的辅助方法
    public static void setCellBackgroundColor(XWPFTableCell cell , String hexColor) {
        
    	CTTc ctTc = cell.getCTTc();
        
        CTTcPr ctTcPr = ctTc.getTcPr();
        
        if (ctTcPr == null) {
            ctTcPr = ctTc.addNewTcPr();
        }

        // 创建并设置底纹元素
        CTShd ctShd = ctTcPr.addNewShd();
        ctShd.setColor("auto");
        ctShd.setFill(hexColor);
    }
	
}
